package controllers

import (
	"fmt"
	"my-go-project/model"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
)

// 申请表接口的请求体
type Application struct {
	PassageID    int    `json:"pa_id"`
	ApplyID      int    `json:"user_id"`
	AdoptProcess int    `json:"adopt_process"`
	Reason       string `json:"reason"`
}
type AdoptProcessjson struct {
	AdoptID      int `json:"adopt_id"`
	AdoptProcess int `json:"adopt_process"`
}
type AdoptEvaluationjson struct {
	AdoptID int    `json:"adopt_id"`
	UserID  int    `json:"user_id"` //评论者自身的ID
	Type    int    `json:"type"`    //1——发起者给申请者的评价；2——申请者给发起者的评价
	Comment string `json:"comment"`
	Score   int    `json:"score"`
}
type SearchIDJson struct {
	AdoptID int `json:"adopt_id"`
}

type AdoptCommentjosn struct {
	AdoptID int `json:"adopt_id"`
	UserID  int `json:"user_id"`
}

type SearchScoreJson struct {
	UserID int `json:"user_id"`
}

// 获取收到具体的某个文章下某个人发起的申请表
func GetAdoptApplications(ctx *gin.Context) {
	var searchjson SearchIDJson
	id, err := strconv.Atoi(ctx.Param("adoptID"))
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数格式错误！",
		})
		return
	}
	searchjson.AdoptID = id
	fmt.Println("searchjson", searchjson)
	application, err := model.FindAdoptApplicationByID(searchjson.AdoptID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "查询失败！",
		})
	}
	ctx.JSON(http.StatusOK, gin.H{
		"message": "successfull",
		"Reason":  application.Reason,
	})
}

// 提交领养申请表__测试成功
func PostAdoptApplication(ctx *gin.Context) {
	var application Application

	if err := ctx.ShouldBindBodyWithJSON(&application); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"data": " 请求体格式错误！",
		})
		return
	}
	//根据文章的ID查找文章的作者
	authorID, err := model.GetAuthorID(application.PassageID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "查询文章作者失败！",
		})
		return
	}
	adoptApplication := model.Adopt{
		PassageID:    application.PassageID,
		ApplyID:      application.ApplyID,
		PromoterID:   authorID,
		AdoptProcess: 1,
		Reason:       application.Reason,
	}

	//TODO: 保存到数据库
	//需要生成消息
	adoptApplication_new, err := adoptApplication.SaveAdoptApplication()
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"data": "申请表保存到数据库失败！",
		})
		return
	}
	//生成记录
	message := model.Message{
		PassageID:  adoptApplication_new.PassageID,
		Type:       "check_notice",
		AdoptID:    adoptApplication_new.AdoptID,
		SenderID:   application.ApplyID,
		ReceiverID: authorID,
	}
	_, err = message.SaveMessage()
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "生成消息记录失败！",
		})
	}
	ctx.JSON(http.StatusOK, gin.H{
		"message": "successfull",
		"data":    message.AdoptID,
	})
}

// 更新领养进程
func UpdateAdoptProcess(ctx *gin.Context) {
	var Updatejson AdoptProcessjson
	if err := ctx.ShouldBindBodyWithJSON(&Updatejson); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"error": "请求体格式错误！",
		})
		return
	}
	fmt.Println("Updatejson", Updatejson)
	//TODO: 更新数据库
	application, err := model.FindAdoptApplicationByID(Updatejson.AdoptID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "未在数据库中查找到对应的申请表！",
		})

		return
	}
	application.AdoptProcess = Updatejson.AdoptProcess
	_, err = application.UpdateAdoptApplication()
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "领养进程在数据库中更新失败！",
		})

	}
	//同意领养
	if application.AdoptProcess == 3 {
		message := model.Message{
			PassageID:  application.PassageID,
			Type:       "request_success",
			SenderID:   application.PromoterID,
			ReceiverID: application.ApplyID,
			AdoptID:    application.AdoptID,
		}
		_, err = message.SaveMessage()
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{
				"error": "生成消息记录失败！",
			})
		}
	}
	//拒绝领养-申请者接收消息
	if application.AdoptProcess == -1 {
		message := model.Message{
			PassageID:  application.PassageID,
			Type:       "request_fail",
			SenderID:   application.PromoterID,
			ReceiverID: application.ApplyID,
			AdoptID:    application.AdoptID,
		}
		_, err = message.SaveMessage()
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{
				"error": "生成消息记录失败！",
			})
		}

	}
	//领养成功-领养方接收消息
	if application.AdoptProcess == 4 {
		message := model.Message{
			PassageID:  application.PassageID,
			Type:       "adopt_success",
			SenderID:   application.PromoterID,
			ReceiverID: application.ApplyID,
			AdoptID:    application.AdoptID,
		}
		_, err = message.SaveMessage()
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{
				"error": "生成消息记录失败！",
			})
		}
	}
	//领养失败-申请者接收消息
	if application.AdoptProcess == -2 {
		message := model.Message{
			PassageID:  application.PassageID,
			Type:       "adopt_fail",
			SenderID:   application.PromoterID,
			ReceiverID: application.ApplyID,
			AdoptID:    application.AdoptID,
		}
		_, err = message.SaveMessage()
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{
				"error": "生成消息记录失败！",
			})
		}
	}
	ctx.JSON(http.StatusOK, gin.H{
		"message": "successfull",
		"data":    application.AdoptProcess,
	})
}

// 获取领养进程
func GetAdoptProcess(ctx *gin.Context) {
	//TODO: 查询数据库
	var getprocess SearchIDJson
	id, err := strconv.Atoi(ctx.Param("adoptID"))
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数格式错误！",
		})
		return
	}
	getprocess.AdoptID = id
	application, err := model.FindAdoptApplicationByID(getprocess.AdoptID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "未在数据库中查找到对应的申请表！",
		})
		return
	}
	userP, err := model.GetUserMiniByID(application.PromoterID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "未在数据库中查找到对应的用户！",
		})
		return
	}
	userA, err := model.GetUserMiniByID(application.ApplyID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "未在数据库中查找到对应的用户！",
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"process":  application.AdoptProcess,
		"promoter": userP,
		"apply":    userA,
	})
}

// 获取用户的所有相关的领养进程
func GetUserAdoptProcess(ctx *gin.Context) {
	param := ctx.Param("id")
	userID, err := strconv.Atoi(param)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数格式错误！",
		})
		return
	}

	//再查发起的领养进程的所有进程
	userList, err := model.FindUserAdoptApplication(userID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "未在数据库中查找到对应的申请表！"})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"data": userList,
	})
}

// 根据文章获取领养状态信息
func GetAdoptStatus(ctx *gin.Context) {
	var passageID, err = strconv.Atoi(ctx.Param("p_id"))
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数格式错误！",
		})
		return
	}
	userID, err := strconv.Atoi(ctx.Param("u_id"))
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数格式错误！",
		})
		return
	}
	//调用数据库查询接口
	endAdopt, err := model.FindAdoptStatus(passageID, userID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "未在数据库中查找到对应的申请表！",
		})
		return
	}
	//没有人领养成功该用户自己也没有申请或者申请过但是失败了1
	if endAdopt == nil {
		ctx.JSON(http.StatusOK, gin.H{
			"status": 1,
		})
		return
	}
	//领养完成是自己领养的
	if endAdopt.AdoptProcess >= 4 && endAdopt.ApplyID == userID {
		ctx.JSON(http.StatusOK, gin.H{
			"status": 2,
		})
		return
	}
	//没有人领养成功但是该用户自己已经申请了领养不能再次申请
	if endAdopt.ApplyID == userID {
		ctx.JSON(http.StatusOK, gin.H{
			"status": -1,
		})
		return
	}
	//其他人领养成功
	ctx.JSON(http.StatusOK, gin.H{
		"status": 2,
	})
}

// 提交评价信息
func PostAdoptEvaluation(ctx *gin.Context) {
	var evaluationjson AdoptEvaluationjson
	if err := ctx.ShouldBindBodyWithJSON(&evaluationjson); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"error": "请求体格式错误！",
		})
		return
	}
	//TODO: 更新数据库
	apllication, err := model.FindAdoptApplicationByID(evaluationjson.AdoptID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "未在数据库中查找到对应的申请表！",
		})
		return
	}
	var message model.Message
	//判断双方是否都完成评价
	evaluation, err := model.SearchComment(evaluationjson.AdoptID)
	if err != nil {
		//还没有开始评价
		if evaluationjson.Type == 1 {
			//发起者评价申请者
			evaluation = model.AdoptComment{
				AdoptID:         evaluationjson.AdoptID,
				PromoterID:      evaluationjson.UserID,
				PromoterScore:   evaluationjson.Score,
				PromoterComment: evaluationjson.Comment,
				Adopt:           apllication,
			}
			//申请者接收消息
			message = model.Message{
				PassageID:  apllication.PassageID,
				Type:       "comment_notice",
				SenderID:   evaluationjson.UserID,
				ReceiverID: apllication.ApplyID,
				AdoptID:    evaluationjson.AdoptID,
			}

		} else if evaluationjson.Type == 2 {
			//申请者给发起者评价
			evaluation = model.AdoptComment{
				AdoptID:      evaluationjson.AdoptID,
				ApplyID:      evaluationjson.UserID,
				ApplyScore:   evaluationjson.Score,
				ApplyComment: evaluationjson.Comment,
				Adopt:        apllication,
			}
			message = model.Message{
				PassageID:  apllication.PassageID,
				Type:       "comment_notice",
				SenderID:   evaluationjson.UserID,
				ReceiverID: apllication.PromoterID,
				AdoptID:    evaluationjson.AdoptID,
			}
		}
		apllication.AdoptProcess = 5
		_, err = evaluation.Create()
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{
				"error": "评价信息保存到数据库失败！",
			})
			return
		}
		_, err = message.SaveMessage()
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{
				"error": "生成消息记录失败！",
			})
			return
		}
	} else {
		//判断当前的评论是谁发起的
		if evaluationjson.Type == 1 {
			//发起者评价申请者
			evaluation.PromoterID = evaluationjson.UserID
			evaluation.PromoterScore = evaluationjson.Score
			evaluation.PromoterComment = evaluationjson.Comment
			//申请者接收消息
			message = model.Message{
				PassageID:  apllication.PassageID,
				Type:       "comment_notice",
				SenderID:   evaluationjson.UserID,
				ReceiverID: apllication.ApplyID,
				AdoptID:    evaluationjson.AdoptID,
			}

		} else if evaluationjson.Type == 2 {
			//申请者对发起者的评论
			evaluation.ApplyID = evaluationjson.UserID
			evaluation.ApplyScore = evaluationjson.Score
			evaluation.ApplyComment = evaluationjson.Comment
			//发起者接收消息
			message = model.Message{
				PassageID:  apllication.PassageID,
				Type:       "comment_notice",
				SenderID:   evaluationjson.UserID,
				ReceiverID: apllication.PromoterID,
				AdoptID:    evaluationjson.AdoptID,
			}
		}
		_, err = message.SaveMessage()
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{
				"error": "生成消息记录失败！",
			})
			return
		}
		_, err = evaluation.SetComments()
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{
				"error": "评论消息保存失败！",
			})
			return
		}
		//双方都进行了评价
		apllication.AdoptProcess = 6
	}
	//更新领养进程
	_, err = apllication.UpdateAdoptApplication()
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "评价信息在数据库中更新失败！",
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"message": "successfull",
		"data":    apllication,
	})
}

// 获取评价信息
func GetAdoptEvaluation(ctx *gin.Context) {
	var searchjson AdoptCommentjosn
	adoptID, err := strconv.Atoi(ctx.Param("adoptID"))
	userID, err := strconv.Atoi(ctx.Param("userID"))
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数格式错误！",
		})
		return
	}
	searchjson.AdoptID = adoptID
	searchjson.UserID = userID
	//TODO: 查询数据库
	comment, err := model.GetAdoptCommentMiniByID(searchjson.AdoptID, searchjson.UserID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "未在数据库中查找到对应的申请表！",
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"message": "successfull",
		"data":    comment,
	})
}

// 获取个人评价信息
func GetAdoptEvaluationByUser(ctx *gin.Context) {
	var searchjson SearchScoreJson
	id, err := strconv.Atoi(ctx.Param("id"))
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数格式错误！",
		})
		return
	}
	searchjson.UserID = id
	scoreList, applyuser, promotuser, err := model.SearchScoreByUserID(searchjson.UserID)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"error": "未在数据库中查找到对应的评价信息！",
		})
		return
	}
	if len(scoreList) == 0 {
		ctx.JSON(http.StatusOK, gin.H{
			"message": "successfull",
			"data":    "暂无评价信息！",
		})
		return
	}
	sum := 0
	for _, score := range scoreList {
		sum += score
	}
	avg := sum / len(scoreList)
	ctx.JSON(http.StatusOK, gin.H{
		"scoreavg":   avg,
		"applyuser":  applyuser,
		"promotuser": promotuser,
	})
}
